package jhunter.web.mvc.params;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class SessionFlashManger implements FlashManger {

	private static final String SESSION_KEY = SessionFlashManger.class.getName() + "_KEY";

	private static final Object writeLock = new Object();

	private int flashMapTimeout = 180;

	@SuppressWarnings("unchecked")
	@Override
	public FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {
		String uri = request.getRequestURI();
		HttpSession session = request.getSession(false);
		if (session != null && session.getAttribute(SESSION_KEY) != null) {
			List<FlashMap> flashMaps = (List<FlashMap>) session.getAttribute(SESSION_KEY);
			// find this uri
			List<FlashMap> matchList = new ArrayList<FlashMap>();
			List<FlashMap> toRemoveList = new ArrayList<FlashMap>();
			for (FlashMap flashMap : flashMaps) {
				String furi = flashMap.getRequestUri();
				if (uri.equals(furi)) {
					matchList.add(flashMap);
					toRemoveList.add(flashMap);
				} else if (flashMap.isExpired()) {
					toRemoveList.add(flashMap);
				}
			}
			if (!toRemoveList.isEmpty()) {
				synchronized (writeLock) {
					flashMaps.removeAll(toRemoveList);
					session.setAttribute(SESSION_KEY, flashMaps);
				}
			}
			if (matchList.size() > 0) {
				Collections.sort(matchList);
				return matchList.get(0);
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
		if (flashMap == null || flashMap.size() == 0) {
			return;
		}
		String path = decodeAndNormalizePath(flashMap.getRequestUri(), request);
		flashMap.setRequestUri(path);
		flashMap.startExpirationPeriod(this.flashMapTimeout);

		synchronized (writeLock) {
			HttpSession session = request.getSession(false);
			List<FlashMap> allMaps = null;
			if (session != null && session.getAttribute(SESSION_KEY) != null) {
				allMaps = (List<FlashMap>) session.getAttribute(SESSION_KEY);
			}
			allMaps = (allMaps == null) ? new CopyOnWriteArrayList<FlashMap>() : allMaps;
			allMaps.add(flashMap);
			request.getSession().setAttribute(SESSION_KEY, allMaps);
		}
	}

	protected String decodeAndNormalizePath(String path, HttpServletRequest request) {
		return path;
	}

}
